<!--
 * @Author: wangyage wangyage@zhejianglab.com
 * @Date: 2022-08-05 15:12:39
 * @LastEditors: wangyage wangyage@zhejianglab.com
 * @LastEditTime: 2022-10-09 18:45:00
 * @FilePath: \aiworks\frontend\src\components\knowledge-gis\autoTabs.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <a-tabs
    class="slide-position-panel"
    tab-position="left"
    :active-key="activeKey"
    @change="onChange($event, true)"
  >
    <a-tab-pane v-for="each in classShapeList" :key="each.label">
      <span slot="tab">
        {{ each.label }}
      </span>
      <div
        class="slide-item-container"
        :style="{ '--after-height': `${itemContainerAfterHeight}px` }"
      >
        <div
          v-for="item in itemsShape"
          :key="item.id"
          class="slide-item"
          :class="item.isLast ? 'last-item' : ''"
        >
          <slot name="slidItemSlot" :data="item"></slot>
        </div>
      </div>
    </a-tab-pane>
  </a-tabs>
</template>
<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'

const elementSelector = '.ant-kg-appl-tabs .ant-kg-appl-tabs-left-content'

@Component({
  components: {},
})
export default class SlidePosition extends Vue {
  @Prop({ type: Array, default: () => [] }) classList!: any[]
  @Prop({ type: Array, default: () => [] }) items!: any[]

  public activeKey: any = this.classList[0]

  public itemContainerAfterHeight: any = 0

  public previousThrottle: any = null

  /** 渲染出来的整形数据 */
  public classShapeList: any = []
  public itemsShape: any = []

  /** 最后一种数据类型的数据有多少个 */
  private get countOfLastType() {
    return this.classShapeList.slice(-1)[0].length
  }

  shapeData() {
    const result: any = []
    let content: any = []
    console.log('this.classList-this.items:', this.classList, this.items)
    this.classList.forEach((label: any) => {
      const array = this.items.filter((item: any) => label === item.attrName)
      result.push({
        label,
        start: result.length > 0 ? result.slice(-1)[0].end + 1 : 0,
        end:
          result.length > 0
            ? result.slice(-1)[0].end + array.length
            : array.length - 1,
        length: array.length,
      })
      if (content.length > 0) {
        // 标记每一类的最后一个item
        content[content.length - 1].isLast = true
      }
      content = content.concat(array)
    })
    this.classShapeList = result
    this.itemsShape = content
    console.log(this.classShapeList, this.itemsShape)
  }

  /**
   * 点击左侧tab选项卡进行数据切换
   * @param item
   * @param updateScroll
   */
  onChange(item: any, updateScroll: boolean) {
    this.activeKey = item
    if (!updateScroll) {
      return
    }
    /** 根据位置信息进行定位 */
    const { start } = this.classShapeList?.find((l: any) => l.label === item)
    const slidesContentEle = this.$el.querySelector(
      elementSelector
    ) as HTMLElement
    const slideItemHeight = (
      this.$el.querySelectorAll('.slide-item')[1] as HTMLElement
    ).clientHeight
    console.log(
      'onChange:',
      slidesContentEle,
      slideItemHeight,
      start,
      slideItemHeight * start
    )
    slidesContentEle.scrollTop = slideItemHeight * start
  }
  /**
   * 滚动条事件
   */
  handleScrollInTab() {
    const slidesContentEle = this.$el.querySelector(
      elementSelector
    ) as HTMLElement
    const slideItemHeight = (
      this.$el.querySelectorAll('.slide-item')[1] as HTMLElement
    ).offsetTop
    let activeTabPos: number = this.classShapeList?.findLastIndex(
      (itemPos: any) =>
        itemPos.start <= slidesContentEle.scrollTop / slideItemHeight
    )
    if (
      slidesContentEle.scrollTop >
      this.classShapeList[activeTabPos].end * slideItemHeight
    ) {
      activeTabPos += 1
    }
    if (this.classShapeList[activeTabPos]) {
      this.onChange(this.classShapeList[activeTabPos].label, false)
    }
  }
  /**
   * 动态计算左侧需要插入空白元素的尺寸（高度）
   */
  setItemContainerAfterHeight() {
    const slidesContentEle = this.$el.querySelector(
      elementSelector
    ) as HTMLElement
    const slideContentHeight = (
      this.$el.querySelector(
        '.ant-kg-appl-tabs-content.ant-kg-appl-tabs-content-animated.ant-kg-appl-tabs-left-content'
      ) as HTMLElement
    ).offsetHeight
    const slideItemHeight = (
      this.$el.querySelectorAll('.slide-item')[1] as HTMLElement
    ).offsetTop
    this.itemContainerAfterHeight = Math.max(
      0,
      slideContentHeight - slideItemHeight * this.countOfLastType
    )
    slidesContentEle.scrollTop = Math.min(
      slidesContentEle.scrollTop,
      this.itemsShape.length * slideItemHeight +
        this.itemContainerAfterHeight -
        slideContentHeight
    )
  }
  throttleOnResize() {
    const now = Date.now()
    if (now - this.previousThrottle > 100) {
      this.setItemContainerAfterHeight()
      this.previousThrottle = Date.now()
    }
  }

  @Watch('items', { immediate: true, deep: true })
  handleItems(newValue: any) {
    if (newValue) {
      this.shapeData()
      setTimeout(() => {
        // 监听滚动条位置，动态更新tab分类的activeKey
        const slidesContentEle = this.$el.querySelector(
          elementSelector
        ) as HTMLElement
        // eyes图标进行点击操作时，会修改items数据，这里不需要设置scrollTop = 0
        // slidesContentEle.scrollTop = 0
        slidesContentEle.addEventListener('scroll', this.handleScrollInTab)
        this.setItemContainerAfterHeight()
        this.previousThrottle = new Date()
        window.addEventListener('resize', this.throttleOnResize)
      }, 10)
    }
  }
  mounted() {}
  beforeDestroy() {
    window.removeEventListener('resize', this.throttleOnResize)
  }
}
</script>
<style lang="less" scoped>
.slide-position-panel {
  height: 240px;

  .slide-item-container {
    .slide-item {
      align-items: center;
      background: #f9f9f9;
      cursor: inherit;
      display: flex;
      height: 50px;
      justify-content: flex-start;
      margin-bottom: 5px;
      margin-left: 5px;
      text-align: center;
      width: 170px;
    }

    .last-item {
      border-bottom: 1px solid #e9e9eb;
    }

    .slide-item-avatar {
      height: 30px;
      width: 30px;
    }

    &::after {
      content: '';
      display: block;
      height: var(--after-height);
    }
  }

  /deep/ .ant-kg-appl-tabs-content {
    height: 100%;
    overflow: auto;
  }

  /deep/ .ant-kg-appl-tabs-left-bar {
    .ant-tabs-ink-bar {
      display: none !important;
    }
  }

  /deep/ .ant-kg-appl-tabs-left-content {
    height: 100%;
    overflow-x: hidden;
    overflow-y: scroll;
    padding-left: 0;

    &::-webkit-scrollbar {
      height: 6px;
      visibility: hidden;
      width: 5px;
    }

    &::-webkit-scrollbar-thumb {
      background: rgba(144, 147, 153, 0.5);
      border-radius: 6px;
      visibility: hidden;
    }

    &:hover {
      &::-webkit-scrollbar {
        visibility: visible;
      }

      &::-webkit-scrollbar-thumb {
        visibility: visible;
      }
    }

    &::-webkit-scrollbar-track {
      background: transparent;
      border-radius: 5px;
    }
  }

  /deep/ .ant-kg-appl-tabs-tab-active {
    ::before {
      content: '|';
    }
  }
}
</style>
